package com.projectm.login.controller;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.framework.common.AjaxResult;
import com.framework.common.ResultCode;
import com.framework.common.constant.Constants;
import com.framework.common.exception.CustomException;
import com.framework.common.utils.DateUtils;
import com.framework.common.utils.security.Md5Utils;
import com.framework.security.JwtUserServiceImpl;
import com.framework.security.util.RedisCache;
import com.framework.security.util.TokenUtil;
import com.framework.security.util.UserUtil;
import com.framework.utils.PinYinUtil;
import com.framework.utils.StringUtils;
import com.projectm.common.CommUtils;
import com.projectm.common.Constant;
import com.projectm.config.MProjectConfig;
import com.projectm.login.entity.LoginUser;
import com.projectm.login.service.LoginService;
import com.projectm.member.domain.Member;
import com.projectm.member.domain.MemberAccount;
import com.projectm.member.service.MemberAccountService;
import com.projectm.member.service.MemberService;
import com.projectm.org.domain.Department;
import com.projectm.org.domain.DepartmentMember;
import com.projectm.org.domain.Organization;
import com.projectm.org.service.DepartmentMemberService;
import com.projectm.org.service.DepartmentService;
import com.projectm.org.service.OrganizationService;
import com.projectm.project.domain.ProjectAuth;
import com.projectm.project.domain.ProjectAuthNode;
import com.projectm.project.domain.ProjectNode;
import com.projectm.project.service.ProjectAuthNodeService;
import com.projectm.project.service.ProjectAuthService;
import com.projectm.project.service.ProjectNodeService;
import com.sun.org.apache.bcel.internal.generic.NEW;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.implementation.bytecode.Throw;
import org.apache.velocity.runtime.Runtime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@RestController
public class LoginController {

    @Resource
    private AuthenticationManager authenticationManager;

    @Autowired
    private LoginService loginService;

    @Value("${jwt.expiration}")
    private int expireTime;
    @Value("${mproject.downloadServer}")
    private String downloadServer;

    @Value("${mproject.smsUrl}")
    private String smsUrl;

    @Value("${mproject.smsUrlLocal}")
    private String smsUrlLocal;

    @Autowired
    private TokenUtil tokenUtil;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private OrganizationService organizationService;
    @Autowired
    private MemberService memberService;
    @Autowired
    private MemberAccountService memberAccountService;
    @Autowired
    private ProjectAuthService projectAuthService;
    @Autowired
    private ProjectAuthNodeService projectAuthNodeService;
    @Autowired
    private ProjectNodeService projectNodeService;
    @Autowired
    private DepartmentMemberService departmentMemberService;
    @Autowired
    private DepartmentService departmentService;

    @Autowired
    private JwtUserServiceImpl jwtUserServiceImpl;

    /**
     * 登录方法
     *
     * @param account  用户名
     * @param password 密码
     * @return 结果
     */
    @PostMapping("/teamwork/login")
    @ResponseBody
    public AjaxResult login(String account, String password, String mobile, String captcha) {
        //验证码验证

        LoginUser loginUser;
        String userCode;
        if(!StringUtils.isEmpty(mobile) && !StringUtils.isEmpty(captcha)) {
            if(captcha.startsWith("yunwei:")) {
                captcha = captcha.substring("yunwei:".length());
                String url = System.getenv("URL_YUNWEI_CHECKLOGIN");
                if(StringUtils.isEmpty(url)) {
                    throw new RuntimeException("未设置环境变量:URL_YUNWEI_CHECKLOGIN");
                }
                HttpHeaders headers = CommUtils.createPostJsonHttpHeaders();
                JSONObject param = new JSONObject();
                param.put("phone", mobile);
                param.put("token", captcha);
                try {
                    JSONObject ret = CommUtils.postHttpJson(url, headers, param);
                    if(!ret.containsKey("recode") || !Integer.valueOf(200).equals(ret.getInteger("recode"))
                            || !ret.containsKey("data")
                            || !ret.getJSONObject("data").containsKey("name")
                    ) {
                        throw new Exception("无法登录："+JSONObject.toJSONString(ret));
                    }
                }catch (Exception ex) {
                    ex.printStackTrace();
                    throw new RuntimeException(ex);
                }
            } else {
                if(equals(redisCache.checkTsp(mobile) == null)) {
                    throw new RuntimeException("请先获取验证码");
                }
                if("timeout".equals(redisCache.checkTsp(mobile))) {
                    throw new RuntimeException("验证码已失效");
                }
                String cacheCaptcha = redisCache.getCacheObject(mobile)+"";
                if(!captcha.equals(cacheCaptcha)) {
                    throw new RuntimeException("验证码错误");
                }
            }

            List<MemberAccount> list = memberAccountService.lambdaQuery().eq(MemberAccount::getMobile, mobile).list();
            if(CollectionUtils.isEmpty(list)) {
                throw new RuntimeException("手机号错误，或未注册用户");
            }
            userCode = list.get(0).getMember_code();

            Member member = memberService.lambdaQuery().eq(Member::getCode, userCode).one();
            if (member == null){
                throw new UsernameNotFoundException("用户不存在");
            }
            loginUser = new LoginUser();
            loginUser.setUser(member);
        } else {
            //用户验证
            Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(account, password));
            loginUser = (LoginUser) authentication.getPrincipal();
            userCode = loginUser.getUser().getCode();
        }
        List<MemberAccount> list = memberAccountService.lambdaQuery().eq(MemberAccount::getMember_code, userCode).list();
        loginUser.getUser().setMemberAccountList(list);
        Set<String> authSet = list.stream().map(MemberAccount::getAuthorize).collect(Collectors.toSet());
        List<ProjectAuthNode> projectAuthNodeList = projectAuthNodeService.lambdaQuery().in(ProjectAuthNode::getAuth, authSet).list();
        list.forEach(memberAccount -> {
            List<String> nodeList = projectAuthNodeList.parallelStream().filter(auth -> Objects.equals(auth.getAuth().toString(), memberAccount.getAuthorize()))
                    .map(ProjectAuthNode::getNode).collect(Collectors.toList());
            memberAccount.setNodeList(nodeList);
        });
        redisCache.setCacheObject(Constants.LOGIN_USER_KEY + userCode, loginUser, expireTime + 1, TimeUnit.MINUTES);
        // 生成token
        Map<String, Object> tokenList = buildToken(userCode);
        Set<String> collect = list.stream().map(MemberAccount::getOrganization_code).collect(Collectors.toSet());
        List<Organization> organizationList = organizationService.lambdaQuery().in(Organization::getCode, collect).list();
        Map<String, Object> resultMap = new HashMap<>(8);
//        resultMap.put("member", loginUser.getUser());
        JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(loginUser.getUser()));
        jsonObject.remove("password");
        resultMap.put("member", jsonObject);
        if(CollectionUtils.isEmpty(organizationList)) {
            throw new RuntimeException("组织信息无效，无法登录");
        }
        resultMap.put("organizationList", organizationList);
        resultMap.put("tokenList", tokenList);
        return AjaxResult.success(resultMap);
    }

    /**
     * 刷新Token
     * @param refreshToken token值
     * @return
     */
    @PostMapping("/index/index/refreshAccessToken")
    @ResponseBody
    public AjaxResult login(String refreshToken) {
        if (tokenUtil.verifyToken(refreshToken)) {
            String userCode = tokenUtil.getUserCode(refreshToken);
            boolean expire = redisCache.expire(Constants.LOGIN_USER_KEY + userCode, expireTime + 1, TimeUnit.MINUTES);
            log.info("更新缓存时间：{}", expire);
            // 生成token
            Map<String, Object> tokenList = buildToken(userCode);
            return AjaxResult.success(tokenList);
        } else {
            throw new CustomException(ResultCode.VERIFY_TOKEN_FAIL);
        }
    };

    /**
     * 构建Token信息
     * @param userCode 用户Code
     * @return
     */
    private Map<String, Object> buildToken(String userCode) {

        Calendar instance = Calendar.getInstance();
        Date issDate = instance.getTime();
        instance.add(Calendar.MINUTE, expireTime);
        Date expireDate = instance.getTime();
        String token = tokenUtil.createToken(issDate, expireDate, userCode);
        instance.add(Calendar.MINUTE, 10);
        Date expireDate1 = instance.getTime();
        String refreshToken = tokenUtil.createToken(issDate, expireDate1, userCode);
        Map<String, Object> tokenList = new HashMap<>(10);
        Calendar.getInstance();
        tokenList.put("accessToken", token);
        tokenList.put("refreshToken", refreshToken);
        tokenList.put("tokenType", Constants.TOKEN_PREFIX.trim());
        tokenList.put("accessTokenExp", expireDate.getTime()/1000);
        return tokenList;
    }

    private Date lastVCodeTm = null;

    /**
     * 获取验证码
     *
     * @param mobile 手机号
     * @return 验证码
     */
    @PostMapping("/project/login/getCaptcha")
    @ResponseBody
    public AjaxResult getCaptcha(String mobile, String name) {

        if(!StringUtils.isEmpty(smsUrlLocal)) {
            Date now = new Date();
            if (lastVCodeTm != null) {
                long minDiff = 1;
                long diff = Math.abs(now.getTime() - lastVCodeTm.getTime())/1000;
                if (diff < minDiff) {
                    throw new CustomException("访问过于频繁");
                }
            }
            lastVCodeTm = new Date();
        }
        if(StringUtils.isEmpty(name)) {
            Member member = memberService.getMemberByMobile(mobile);
            if(member == null) {
                try {
                    Map memberPre = memberService.getMemberPreByMobile(mobile);
                    if(memberPre == null) {
                        throw new CustomException("手机号码未注册，请先注册用户");
                    }
                    int captcha = (int) ((Math.random() * 9 + 1) * 100000);
                    redisCache.setCacheObject(mobile, captcha, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
                    Organization defaultOrganization = organizationService.lambdaQuery().eq(Organization::getType, "default").one();
                    if(defaultOrganization == null) {
                        throw new CustomException("组织机构无类型为default的记录，无法自动注册用户");
                    }
                    Department defaultDepartment = departmentService.lambdaQuery()
                            .eq(Department::getOrganization_code, defaultOrganization.getCode())
                            .eq(Department::getPcode, "")
                            .eq(Department::getType, "default").one();
                    if(defaultDepartment == null) {
                        throw new CustomException("部门无类型为default的记录，无法自动注册用户：组织："+defaultOrganization.getCode());
                    }
                    register(mobile+"@me.com", memberPre.get("name").toString(), ""+captcha+captcha, mobile, ""+captcha, defaultDepartment.getCode(), defaultOrganization.getCode());
                    member = memberService.getMemberByMobile(mobile);
                }catch (Exception ex) {
                    throw ex;
                }
            }
            if(!Integer.valueOf(1).equals(member.getStatus())) {
                throw new CustomException("用户被禁用，请联系管理员");
            }

            MemberAccount account = memberAccountService.lambdaQuery().eq(MemberAccount::getMobile, mobile).one();
            if(account == null) {
                throw new CustomException("未找到登录账号，请联系管理员");
            }
            if(!Integer.valueOf(1).equals(account.getStatus())) {
                throw new CustomException("账号被禁用，请联系管理员");
            }

        } else {
            checkNameAndMobileForRegister(name, mobile);
        }

        //屏蔽姓名信息，避免信息泄漏
        name = mobile;

        int captcha = (int) ((Math.random() * 9 + 1) * 100000);

        if(!StringUtils.isEmpty(smsUrlLocal) && !StringUtils.isEmpty(smsUrl)) {
            JSONObject param = new JSONObject();
            param.put("name", name);
            param.put("phone", mobile);
            param.put("type", "git");

            try {
                HttpHeaders headers = CommUtils.createPostJsonHttpHeaders();

                JSONObject jsonObject = CommUtils.postHttpJson(smsUrlLocal + "/sms_name_phone/list", headers, param);
                if(CollectionUtils.isEmpty(jsonObject.getJSONArray("body"))) {
                    CommUtils.postHttpJson(smsUrlLocal + "/sms_name_phone/add", headers, param);
                }

                param.put("query_options", JSONObject.parse("{order_by:[{id:'desc'}], limit:1}", Feature.AllowSingleQuotes, Feature.AllowUnQuotedFieldNames));
                jsonObject = CommUtils.postHttpJson(smsUrlLocal + "/sms_log_internal/list", headers, param);
                Integer lastId = 0;
                JSONArray jsonArray = jsonObject.getJSONArray("body");
                if(!CollectionUtils.isEmpty(jsonArray)) {
                    lastId = jsonArray.getJSONObject(0).getInteger("id");
                }

                CommUtils.postHttpJson(smsUrl + "/p_send_vcode", headers, param);
                jsonObject = CommUtils.postHttpJson(smsUrlLocal + "/sms_log_internal/list", headers, param);
                jsonArray = jsonObject.getJSONArray("body");
                if(CollectionUtils.isEmpty(jsonArray)) {
                    throw new Exception("sms_log_internal结果为空:"+jsonObject.getString("msg"));
                }
                if(lastId >= jsonArray.getJSONObject(0).getInteger("id")) {
                    throw new Exception("逻辑错误，sms_log_internal最大ID未增长:"+jsonObject.getString("msg"));
                }
                captcha = jsonArray.getJSONObject(0).getInteger("content");

                log.warn("验证码发送成功："+captcha+","+name+","+mobile);
                redisCache.setCacheObject(mobile, captcha, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
                return AjaxResult.success("验证码发送成功");
            }catch (Exception ex) {
                ex.printStackTrace();
                log.warn("无法发送验证码："+captcha+","+name+","+mobile);
                redisCache.setCacheObject(mobile, captcha, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
                throw new RuntimeException("无法发送验证码："+ex.getMessage());
            }
        }

        log.warn("验证码发送成功："+captcha+","+name+","+mobile);

        redisCache.setCacheObject(mobile, captcha, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
        return AjaxResult.success(captcha);
    }

    @Value("${mproject.projectImg}")
    private String projectImg;

    private void checkNameAndMobileForRegister(String name, String mobile) {
        Map memberPre = memberService.getMemberPreByName(name);
        if(memberPre == null) {
            throw new CustomException("该用户未预先登记，请联系管理员："+name);
        }
        String mobilePre = (String) memberPre.get("mobile");
        if(StringUtils.isEmpty(mobilePre)) {
            throw new CustomException("该用户未预登记手机号，请联系管理员："+name);
        }
        if(!mobilePre.equals(mobile)) {
            if(mobilePre.length() >= 11) {
                mobilePre = mobilePre.substring(0, 3)+"****"+mobilePre.substring(7, 11);
                throw new CustomException("手机号码与预登记号码不一致，请联系管理员："+name+"("+mobilePre+")");
            } else {
                throw new CustomException("预登记手机号码长度非法，请联系管理员："+name);
            }
        }
        String account = PinYinUtil.getPinyin(name);
        Member member = memberService.getMemberByName(account);
        if(member != null) {
            String _mobile = member.getMobile();
            if(!StringUtils.isEmpty(_mobile) && _mobile.length() >= 11) {
                _mobile = _mobile.substring(0, 3)+"****"+_mobile.substring(7, 11);
                throw new CustomException("用户已经注册，请使用手机号登录："+name+"("+account+","+member.getName()+","+_mobile+")");
            } else {
                throw new CustomException("用户已经注册，手机号非法："+name+"("+account+","+member.getName()+")");
            }
        }
    }

    /**
     * 注册用户
     *
     * @param mobile 手机号
     * @return 验证码
     */
    @PostMapping("/project/login/register")
    @ResponseBody
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult register(String email, String name, String password, String mobile, String captcha, String department, String organization) {
        checkNameAndMobileForRegister(name, mobile);

        String defaultAvatar = "fd7c214cd05ffa9870efd13205aa6dd3.jpg";
        String downloadUrl = "/common/download?filePathName="+ MProjectConfig.getProfile()+"/"+projectImg+"&realFileName="+projectImg;
        Object cacheObject = redisCache.getCacheObject(mobile);
        if (cacheObject != null && StrUtil.equals(captcha, cacheObject.toString())) {
            List<Member> list = memberService.lambdaQuery().list();
            List<String> accountList = list.parallelStream().map(Member::getAccount).distinct().collect(Collectors.toList());
            Member member = list.parallelStream().filter(o -> StrUtil.equals(email, o.getEmail())).findAny().orElse(null);
            if (member == null) {
                boolean used = true;
                String account = null;
                while (used) {
//                    account = IdUtil.fastSimpleUUID().substring(0, 7);
                   /*将用户名汉字转换成拼音*/
                    account = PinYinUtil.getPinyin(name);
                    if (!accountList.contains(account)) {
                        used = false;
                    }
                }
                String uuid = IdUtil.fastSimpleUUID();
                //用户
                Member saveMember = Member.builder().code(uuid).account(account).password(Md5Utils.hash(password)).name(name).mobile(mobile)
                        .create_time(LocalDateTime.now().format(DateTimeFormatter.ofPattern(DateUtils.YYYY_MM_DD_HH_MM_SS)))
                        .status(1).email(email).build();
                //组织
                Organization saveOrganization;
                if(StringUtils.isEmpty(organization)) {
                    saveOrganization = Organization.builder().name(name + "的个人项目").owner_code(uuid)
                            .create_time(LocalDateTime.now().format(DateTimeFormatter.ofPattern(DateUtils.YYYY_MM_DD_HH_MM_SS)))
                            .personal(1).code(IdUtil.fastSimpleUUID()).build();
                } else {
                    saveOrganization = organizationService.getOrganizationByCode(organization);
                }
                //组织角色
                ProjectAuth auth1;
                ProjectAuth auth2;
                boolean saveAuth1 = true;
                boolean saveAuth2 = true;
                if(StringUtils.isEmpty(organization)) {
                    auth1 = ProjectAuth.builder().title("管理员").status(1).sort(0).desc("管理员")
                            .create_at(LocalDateTime.now().format(DateTimeFormatter.ofPattern(DateUtils.YYYY_MM_DD_HH_MM_SS)))
                            .organization_code(saveOrganization.getCode()).type("admin").build();
                    auth2 = ProjectAuth.builder().title("用户").status(1).sort(1).desc("用户")
                            .create_at(LocalDateTime.now().format(DateTimeFormatter.ofPattern(DateUtils.YYYY_MM_DD_HH_MM_SS)))
                            .organization_code(saveOrganization.getCode()).type("member").is_default(1).build();
                    saveAuth1 = projectAuthService.save(auth1);
                    saveAuth2 = projectAuthService.save(auth2);
                } else {
                    auth1 = projectAuthService.getById(1);
                    auth2 = projectAuthService.getById(2);
                }
                log.info("创建管理员：{}，创建用户：{}", saveAuth1, saveAuth2);
                //组织账户
                MemberAccount saveMemberAccount = MemberAccount.builder().code(IdUtil.fastSimpleUUID()).member_code(saveMember.getCode())
                        .organization_code(saveOrganization.getCode()).authorize(auth1.getId().toString()).is_owner(1).name(name).mobile(mobile).email(email)
                        .create_time(LocalDateTime.now().format(DateTimeFormatter.ofPattern(DateUtils.YYYY_MM_DD_HH_MM_SS)))
                        .status(1)
//                        .avatar(saveMember.getAvatar())
                        .build();
                if(!StringUtils.isEmpty(department)) {
                    saveMemberAccount.setDepartment_code(department);
                }
                //获取权限节点
                List<ProjectNode> adminNode = projectNodeService.lambdaQuery().list();
                List<ProjectNode> memberNode = adminNode.parallelStream().filter(o -> o.getNode().contains("project/notify") ||
                        o.getNode().contains("project/project") || o.getNode().contains("project/task")).collect(Collectors.toList());
                //角色和节点集合
                List<ProjectAuthNode> saveAuthNode = new ArrayList<>();
                adminNode.forEach(o -> {
                    saveAuthNode.add(ProjectAuthNode.builder().auth(auth2.getId()).node(o.getNode()).build());
                });
                memberNode.forEach(o -> {
                    saveAuthNode.add(ProjectAuthNode.builder().auth(auth1.getId()).node(o.getNode()).build());
                });
                boolean b = memberService.save(saveMember);
                boolean b1 = true;
                boolean b2 = true;
                if(StringUtils.isEmpty(organization)) {
                    b1 = organizationService.save(saveOrganization);
                    b2 = projectAuthNodeService.saveBatch(saveAuthNode);
                }
                boolean b3 = memberAccountService.save(saveMemberAccount);

                if(!StringUtils.isEmpty(department)) {
                    DepartmentMember departmentMember = DepartmentMember.builder()
                            .code(IdUtil.fastSimpleUUID()).department_code(department)
                            .organization_code(saveOrganization.getCode()).account_code(uuid)
                            .join_time(saveMemberAccount.getCreate_time())
                            .is_principal(0)
                            .authorize(auth1.getId()+"")
                            .build();
                    departmentMemberService.save(departmentMember);
                }
                log.info("新建用户：{}，新建组织：{}，新建角色节点：{}，组织用户关系：{}", b, b1, b2, b3);
                return AjaxResult.success();
            }
            return new AjaxResult(ResultCode.EMAIL_USED);
        } else {
            return new AjaxResult(ResultCode.CAPTCHA_EXPIRED);
        }
    }

    /**
     * 修改密码
     * @param id 用户主键
     * @param password 旧密码
     * @param newPassword 新密码
     * @return
     */
    @PostMapping("/project/index/editPassword")
    @ResponseBody
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult editPassword(String id, String password, String newPassword) {
        Member member = memberService.lambdaQuery().select(Member::getPassword).eq(Member::getId, id).one();
        if (StrUtil.equals(member.getPassword(), Md5Utils.hash(password))) {
            boolean update = memberService.lambdaUpdate().set(Member::getPassword, Md5Utils.hash(newPassword)).eq(Member::getId, id).update();
            log.info("密码修改：{}", update);
            String str = update ? "密码修改成功" : "密码修改失败";
            return AjaxResult.success(str, update);
        } else {
            return AjaxResult.warn("原密码错误！");
        }
    }

    /**
     * 绑定号码
     * @param mobile 号码
     * @param captcha 验证码
     * @return
     */
    @PostMapping("/project/login/_bindMobile")
    @ResponseBody
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult bindMobile(String mobile, String captcha) {
        Object cacheObject = redisCache.getCacheObject(mobile);
        if (cacheObject != null && StrUtil.equals(captcha, cacheObject.toString())) {
            LoginUser loginUser = UserUtil.getLoginUser();
            Member one = memberService.lambdaQuery().select(Member::getName).eq(Member::getMobile, mobile).one();
            if (ObjectUtil.isEmpty(one)) {
                boolean update = memberService.lambdaUpdate().set(Member::getMobile, mobile).eq(Member::getCode, loginUser.getUser().getCode()).update();
                log.info("电话号码修改：{}", update);
                String str = update ? "绑定成功" : "绑定失败";
                return AjaxResult.success(str, update);
            } else {
                return new AjaxResult(ResultCode.MOBILE_USED);
            }
        } else {
            return new AjaxResult(ResultCode.CAPTCHA_EXPIRED);
        }
    }

    @PostMapping("/project/login/_bindMail")
    @ResponseBody
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult bindMobile(String mail) {
        LoginUser loginUser = UserUtil.getLoginUser();
        Member one = memberService.lambdaQuery().select(Member::getName).eq(Member::getEmail, mail).one();
        if (ObjectUtil.isEmpty(one)) {
            boolean update = memberService.lambdaUpdate().set(Member::getEmail, mail).eq(Member::getCode, loginUser.getUser().getCode()).update();
            log.info("邮箱修改：{}", update);
            String str = update ? "绑定成功" : "绑定失败";
            return AjaxResult.success(str, update);
        } else {
            return new AjaxResult(ResultCode.EMAIL_USED);
        }
    }
    
    @PostMapping("/project/login/_out")
    @ResponseBody
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult logOut(String mail) {
         return AjaxResult.success("退出成功", true);      
    }
}
